import { _decorator, Animation, AudioClip, Collider2D, Component, Contact2DType, EventTouch, Input, input, instantiate, IPhysics2DContact, Node, Prefab, Vec3 } from 'cc';
import { Reward, RewardType } from './Reward';
import { GameManager } from './GameManager';
import { LifeUI } from './UI/LifeUI';
import { BombUI } from './UI/BombUI';
import { ScoreUI } from './UI/ScoreUI';
import { AudioMgr } from './AudioMgr';
const { ccclass, property } = _decorator;

enum ShootType {
    None,
    OneShoot,
    TwoShoot,
    FiveShoot
}

@ccclass('Player')
export class Player extends Component {

    @property
    shootRate:number = 0.5;
    @property(Node)
    bulletParent:Node = null;
    @property(Node)
    bullet1Position:Node = null;
    @property(Node)
    bullet2Position:Node = null;
    @property(Node)
    bullet3Position:Node = null;
    @property(Node)
    bullet3P1:Node = null;
    @property(Node)
    bullet3P2:Node = null;
    @property(Node)
    bullet3P3:Node = null;
    @property(Node)
    bullet3P4:Node = null;
    @property(Node)
    bullet3P5:Node = null;

    @property(Prefab)
    bullet1Prefab:Prefab = null;
    @property(Prefab)
    bullet2Prefab:Prefab = null;
    @property(Prefab)
    bullet3Prefab:Prefab = null;

    @property
    shootType:ShootType = ShootType.OneShoot;
    @property(Animation)
    anim:Animation = null;

    @property(LifeUI)
    lifeUI:LifeUI = null;
    @property
    lifeCount:number = 10;
    @property
    animHit:string = "";
    @property
    animDown:string = "";

    @property
    invincibleTime:number = 1;
    isInvicible:boolean = false;
    invincibleTimer:number = 0;

    @property
    twoShootRate:number = 5;
    twoShootTimer:number = 0;

    @property
    fiveShootRate:number = 5;
    fiveShootTimer:number = 0;

    shootTimer:number = 0;
    collider:Collider2D = null;
    lastReward:Reward = null;
    private canTouchMove:boolean = true;

    @property
    bombNumber:number = 0;
    @property(BombUI)
    bombUI:BombUI = null;

    @property
    private score:number = 0;

    @property(AudioClip)
    bulletAudio:AudioClip = null;

    @property(AudioClip)
    getBombAudio:AudioClip = null;
    @property(AudioClip)
    getDoubleAudio:AudioClip = null;
    @property(AudioClip)
    outPorpAudio:AudioClip = null;

    protected onLoad(): void {
        input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);

        // 碰撞检测
        this.collider = this.getComponent(Collider2D);
        if(this.collider) {
            this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        }
    }

    protected start(): void {
        this.lifeUI.updateLife(this.lifeCount);
    }

    protected onDestroy(): void {
        input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);

        if(this.collider) {
            this.collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        }
    }

    onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {   
        const reward = otherCollider.getComponent(Reward);
        if(reward) {
            this.onContactToReward(reward);
        } else {
            // 这里可能碰撞的是敌人，也可能是敌人的子弹
            this.onContactToEnemy(selfCollider, otherCollider, contact);
        }
    }

    onContactToEnemy(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        if(this.isInvicible) return;

        AudioMgr.inst.playOneShot(this.outPorpAudio, 1);
        this.isInvicible = true;
        
        this.lifeCount -= 1;
        
        this.lifeUI.updateLife(this.lifeCount);
        if(this.lifeCount > 0) {
            this.anim.play(this.animHit);
        } else {
            this.anim.play(this.animDown);
        }

        if(this.lifeCount <= 0) {
            this.shootType = ShootType.None;
            if(this.collider) {
                this.collider.enabled = false;
            }
            this.scheduleOnce(() => {
                GameManager.getInstance().gameOver();
            }, 0.4);
        }
    }

    onContactToReward(reward: Reward) {
        if(reward == this.lastReward) {
            return;
        }

        this.lastReward = reward;
        switch(reward.rewardType) {
            case RewardType.TwoShoot:
                AudioMgr.inst.playOneShot(this.getDoubleAudio, 1);
                this.transitionShootType(ShootType.TwoShoot);
                break;
            case RewardType.Bomb:
                AudioMgr.inst.playOneShot(this.getBombAudio, 1);
                this.addBomb();
                break;
        }
    }

    // 规定特殊子弹可发射的时间
    transitionShootType(shootType: ShootType) {
        this.shootType = shootType;

        switch(shootType) {
            case ShootType.TwoShoot:
                this.twoShootTimer = 0;
                break;
            case ShootType.FiveShoot:
                this.fiveShootTimer = 0;
                break;
        }
    }

    addBomb() {
        this.bombNumber += 1;
        GameManager.getInstance().addBomb();
    }

    onTouchMove(event:EventTouch) {
        if(!this.canTouchMove) {
            return;
        }
        if(this.lifeCount <= 0) {
            return;
        }
        const p = this.node.position;

        const targetPostion = new Vec3(p.x + event.getDeltaX(), p.y + event.getDeltaY(), p.z);
        if(targetPostion.x < -230) {
            targetPostion.x = -230;
        }
        if(targetPostion.x > 230) {
            targetPostion.x = 230;
        }
        if(targetPostion.y > 380) {
            targetPostion.y = 380;
        }
        if(targetPostion.y < -380) {
            targetPostion.y = -380;
        }
        this.node.setPosition(targetPostion);
    }

    protected update(dt: number): void {
        switch(this.shootType) {
            case ShootType.OneShoot:
                this.oneShoot(dt);
                break;
            case ShootType.TwoShoot:
                this.twoShoot(dt);
                break;
            case ShootType.FiveShoot:
                this.fiveShoot(dt);
                break;
        }

        if(this.isInvicible) {
            this.invincibleTimer += dt;
            if(this.invincibleTimer > this.invincibleTime) {
                this.isInvicible = false;
                this.invincibleTimer = 0;
            }
        }
    }

    oneShoot(dt: number) {
        this.shootTimer += dt;
        if(this.shootTimer >= this.shootRate) {
            AudioMgr.inst.playOneShot(this.bulletAudio, 0.3);
            this.shootTimer = 0;
            const bullet1 = instantiate(this.bullet1Prefab);
            this.bulletParent.addChild(bullet1);
            bullet1.setWorldPosition(this.bullet1Position.worldPosition);
        }
    }

    twoShoot(dt: number) {
        this.twoShootTimer += dt;
        if(this.twoShootTimer > this.twoShootRate) {
            this.transitionShootType(ShootType.OneShoot);
        }

        this.shootTimer += dt;
        if(this.shootTimer >= this.shootRate) {
            AudioMgr.inst.playOneShot(this.bulletAudio, 0.3);
            this.shootTimer = 0;
            const bullet2 = instantiate(this.bullet2Prefab);
            const bullet3 = instantiate(this.bullet2Prefab);
            this.bulletParent.addChild(bullet2);
            this.bulletParent.addChild(bullet3);
            bullet2.setWorldPosition(this.bullet2Position.worldPosition);
            bullet3.setWorldPosition(this.bullet3Position.worldPosition);
        }
    }

    fiveShoot(dt: number) {
        this.fiveShootTimer += dt;

        // 判断子弹持续时间，是否需要切换到默认子弹
        if(this.fiveShootTimer > this.fiveShootRate) {
            this.transitionShootType(ShootType.OneShoot);
        }

        // 子弹的生成逻辑
        this.shootTimer += dt;
        if(this.shootTimer >= this.shootRate) {
            AudioMgr.inst.playOneShot(this.bulletAudio, 0.3);
            this.shootTimer = 0;
            const bullet2 = instantiate(this.bullet3Prefab);
            const bullet3 = instantiate(this.bullet3Prefab);
            const bullet4 = instantiate(this.bullet3Prefab);
            
            this.bulletParent.addChild(bullet2);
            this.bulletParent.addChild(bullet3);
            this.bulletParent.addChild(bullet4);
            
            bullet2.setWorldPosition(this.bullet3P2.worldPosition);
            bullet2.angle = this.bullet3P2.angle;
            bullet3.setWorldPosition(this.bullet3P3.worldPosition);
            bullet3.angle = this.bullet3P3.angle;
            bullet4.setWorldPosition(this.bullet3P4.worldPosition);
            bullet4.angle = this.bullet3P4.angle;
        }
    }

    disableControl() {
        this.canTouchMove = false;
    }
    enableControl() {
        this.canTouchMove = true;
    }
}

